package club.cearnach.api.service.impl;

import club.cearnach.api.annotation.CacheDeleteAll;
import club.cearnach.api.dao.IPersonDao;
import club.cearnach.api.dto.PersonDTO;
import club.cearnach.api.exception.MoviePathException;
import club.cearnach.api.exception.PersonException;
import club.cearnach.api.form.PageBean;
import club.cearnach.api.service.IActorService;
import club.cearnach.api.service.IDirectorService;
import club.cearnach.api.service.IPersonService;
import club.cearnach.api.util.FileUtil;
import club.cearnach.core.property.MovieWebProperties;
import club.cearnach.entity.Person;
import club.cearnach.entity.Place;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.List;

/**
 * @author 阮胜
 * @date 2018/5/12 17:04
 */
@Service
@CacheConfig(cacheNames = "CACHE_PERSON_ENTITY")
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class PersonServiceImpl implements IPersonService {
    public static final String CACHE_PERSON_NAME = "CACHE_PERSON";
    public static final String CACHE_PERSON_FIND_ALL = "CACHE_PERSON_FIND_ALL";
    private final IPersonDao personDao;
    @Autowired
    private MovieWebProperties movieWebProperties;
    @Autowired
    private IActorService actorService;
    @Autowired
    private IDirectorService directorService;
    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    @Autowired
    private CacheManager cacheManager;

    public PersonServiceImpl(IPersonDao personDao) {
        this.personDao = personDao;
    }


    @Override
    public Page<Person> findAll(Pageable pageable) {
        return personDao.findAll(pageable);
    }


    @CacheDeleteAll
    @Override
    public Person save(PersonDTO personDTO) throws IOException, MoviePathException {
        Person person = new Person();
        BeanUtils.copyProperties(personDTO, person);
        MultipartFile file = personDTO.getImageFile();
        if (file != null) {
            String fileName = FileUtil.saveFile(file, movieWebProperties.getUpload().getPersonImagePath());
            person.setImage(fileName);
        }
        Place birthPlace = new Place(personDTO.getState() == null ? 86 : personDTO.getState(),
                personDTO.getProvince(), personDTO.getCity(), personDTO.getDistrict());
        person.setBirthPlace(birthPlace);
        Person p = personDao.save(person);
        actorService.findByName(person.getName())
                .ifPresent(actor -> {
                    actor.setPerson(p);
                    actorService.save(actor);
                });
        directorService.findByName(person.getName())
                .ifPresent(director -> {
                    director.setPerson(p);
                    directorService.save(director);
                });
        return p;
    }

    @Override
    public List<Person> findByName(String name) {
        return personDao.findByName(name);
    }

    @Override
    public Person findByNameOne(String name) {
        List<Person> personList = personDao.findByName(name);
        if (personList != null && personList.size() > 0) {
            return personList.get(0);
        }
        return null;
    }

    @Cacheable(value = CACHE_PERSON_NAME, key = "'person_'+#id")
    @Override
    public Person findById(Integer id) throws PersonException {
        return personDao.findById(id).orElseThrow(() -> new PersonException(PersonException.PERSON_CAN_NOT_FOUND_EXCEPTION));
    }


    @CacheDeleteAll
    @Override
    public void delete(Integer id) throws PersonException {
        personDao.findById(id).orElseThrow(() -> new PersonException(PersonException.PERSON_CAN_NOT_FOUND_EXCEPTION));
        actorService.findByPersonId(id).ifPresent(actor -> actorService.delete(actor.getId()));
        directorService.findByPersonId(id).ifPresent(director -> directorService.delete(director.getId()));
        personDao.deleteById(id);

    }

    @CacheDeleteAll
    @Override
    public long deleteIn(Integer[] idArr) {
        long result = 0;
        for (int id : idArr) {
            try {
                personDao.deleteById(id);
                result++;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    @Cacheable(value = CACHE_PERSON_FIND_ALL, key = "'findAllOrderByCreateDate_'+#pageBean.getPage()+'_'+#pageBean.getSize()")
    @Override
    public Page<Person> findAllOrderByCreateDate(PageBean pageBean) {
        return personDao.findAll(PageRequest.of(pageBean.getPage(), pageBean.getSize(), Sort.by(Sort.Direction.DESC, "createDate")));
    }

    @Override
    public long count() {
        return personDao.count();
    }

}
